﻿using System;
using System.Data;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Forms;
using System.Globalization;
using System.Drawing;
using System.Windows.Forms.Design;

namespace commonV2.controls
{
    public class basePanel : Panel
    {
        public basePanel()
        {
            this.Controls.Add(this.closeBtn);
            this.Controls.Add(this.showHideBtn);
            this.BorderStyle = BorderStyle.Fixed3D;
            closeBtn.Image = Properties.Resources.close;
            closeBtn.SizeMode = PictureBoxSizeMode.CenterImage;
            closeBtn.Size = new System.Drawing.Size(SystemInformation.CaptionButtonSize.Width - 1, SystemInformation.CaptionButtonSize.Height - 1);

            showHideBtn.Image = Properties.Resources.goUp;
            showHideBtn.SizeMode = PictureBoxSizeMode.CenterImage;
            showHideBtn.Size = new System.Drawing.Size(SystemInformation.CaptionButtonSize.Width - 1, SystemInformation.CaptionButtonSize.Height - 1);

            this.closeBtn.Click += new System.EventHandler(OnCloseHandler);
            this.showHideBtn.Click += new System.EventHandler(OnExpandStateChangedHandler);
            this.haveCloseButton = false;
            //this.Visible = true;
            InitSizing();
            ArrangeControls();
            ApplyTheme();
        }

        private ColorTypes _colorType = ColorTypes.Label;
        private ColorTypes myColorType
        {
            set
            {
                _colorType = value;
                ApplyTheme();
            }
            get
            {
                return _colorType;
            }
        }
        protected virtual void ApplyTheme()
        {
            if (Settings.sysIsDesignMode) return;
            ColorSet cs = ThemeLibs.GetColorSet(this.myColorType);
            if (cs != null)
            {
                this.BackColor = cs.BackColor;
                this.ForeColor = cs.ForeColor;
            }
        }


        #region sizing
        // We use mouse move event for the sizing. Unfotunately, the event occurs continuously 
        // so we should have some way to slow down the sizing event.
        // -  In [constMouseMoveInterval] miliseconds : only one sizing event was fired
        // -  [lastSizingTime] : the time that last sizing ocuured. 

        public int minSizingHeight = 0, minSizingWidth = 0;
        private bool _fShowSizing = false;
        private bool fShowSizing
        {
            get
            {
                return _fShowSizing;
            }
            set
            {
                _fShowSizing = value;
                ShowSizing(value);
            }
        }
        private const short constMouseMoveInterval = 50;
        private DateTime lastSizingTime = DateTime.Now;

        // Rectangle after sizing
        Rectangle sizedRec = new Rectangle();

        bool allowResize = false;
        
        //private TextBox test = new TextBox();

        public enum IconLocations : byte { None = 0, TopLeft = 1, TopRight = 4, BottomLeft = 8, BottomRight = 16 }
        public enum SizingOptions : short {None=0,TopLeft=1,TopRight=4,Top=8,
                                           BottomLeft=16, BottomRight=32, Bottom=64,
                                           Left=128, Right=256
                                        };
        private SizingOptions _mySizingOptions = SizingOptions.None;
        public SizingOptions mySizingOptions
        {
            get { return _mySizingOptions; }
            set 
            {
                _mySizingOptions = value;
            }
        }

        private IconLocations _myIconLocations = IconLocations.None;
        public IconLocations myIconLocations
        {
            get { return _myIconLocations; }
            set
            {
                _myIconLocations = value;
            }
        }
        private basePictureBox topLeftSizingBtn = new basePictureBox(),
                            topRightSizingBtn = new basePictureBox(),

                            botLeftSizingBtn = new basePictureBox(),
                            botRightSizingBtn = new basePictureBox(),

                            topSizingBtn = new basePictureBox(),
                            bottomSizingBtn = new basePictureBox(),

                            leftSizingBtn = new basePictureBox(),
                            rightSizingBtn = new basePictureBox();
                            

        private const int constBaseSizingSize = 5;
        private void InitSizing()
        {
            fShowSizing = false;
            lastSizingTime = DateTime.Now;
            this.saveRec = new Rectangle(this.Location, this.Size);
            this.Controls.AddRange( new Control[]{
                                    topRightSizingBtn,topLeftSizingBtn,
                                    botRightSizingBtn,botLeftSizingBtn,
                                    topSizingBtn,bottomSizingBtn,
                                    rightSizingBtn,leftSizingBtn
                                    }
                                );

            //Name
            topRightSizingBtn.Name = "topRightSizing";
            topLeftSizingBtn.Name = "topLeftSizing";

            botLeftSizingBtn.Name = "botLeftSizing";
            botRightSizingBtn.Name = "botRightSizing";

            topSizingBtn.Name = "topSizing";
            bottomSizingBtn.Name = "bottomSizing";
            
            rightSizingBtn.Name = "rightSizing";
            leftSizingBtn.Name = "leftSizing";

            //Anchor and Cursor 
            topLeftSizingBtn.myColorType = ColorTypes.HiLight;
            this.topLeftSizingBtn.Size = new Size(constBaseSizingSize, constBaseSizingSize);
            this.topLeftSizingBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
            this.topLeftSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeNWSE;

            this.topRightSizingBtn.myColorType = ColorTypes.HiLight;
            this.topRightSizingBtn.Size = new Size(constBaseSizingSize, constBaseSizingSize);
            this.topRightSizingBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.topRightSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeNESW;

            this.botLeftSizingBtn.myColorType = ColorTypes.HiLight;
            this.botLeftSizingBtn.Size = new Size(constBaseSizingSize, constBaseSizingSize);
            this.botLeftSizingBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.botLeftSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeNESW;

            this.botRightSizingBtn.myColorType = ColorTypes.HiLight;
            this.botRightSizingBtn.Size = new Size(constBaseSizingSize, constBaseSizingSize);
            this.botRightSizingBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.botRightSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeNWSE;

            this.topSizingBtn.myColorType = ColorTypes.HiLight;
            this.topSizingBtn.Size = new Size(6*constBaseSizingSize, constBaseSizingSize);
            this.topSizingBtn.Anchor = System.Windows.Forms.AnchorStyles.Top;
            this.topSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeNS;

            this.bottomSizingBtn.myColorType = ColorTypes.HiLight;
            this.bottomSizingBtn.Size = new Size(6 * constBaseSizingSize, constBaseSizingSize+4);
            this.bottomSizingBtn.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
            this.bottomSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeNS;

            this.leftSizingBtn.myColorType = ColorTypes.HiLight;
            this.leftSizingBtn.Size = new Size(constBaseSizingSize,6*constBaseSizingSize);
            this.leftSizingBtn.Anchor = System.Windows.Forms.AnchorStyles.Left;
            this.leftSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeWE;

            this.rightSizingBtn.myColorType = ColorTypes.HiLight;
            this.rightSizingBtn.Size = new Size(constBaseSizingSize,6*constBaseSizingSize);
            this.rightSizingBtn.Anchor = System.Windows.Forms.AnchorStyles.Right;
            this.rightSizingBtn.Cursor = System.Windows.Forms.Cursors.SizeWE;

            //Sizing Events
            this.topLeftSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.topLeftSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.topLeftSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.topRightSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.topRightSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.topRightSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.botLeftSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.botLeftSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.botLeftSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.botRightSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.botRightSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.botRightSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.topSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.topSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.topSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.bottomSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.bottomSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.bottomSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.leftSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.leftSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.leftSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);

            this.rightSizingBtn.MouseMove += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseMove);
            this.rightSizingBtn.MouseDown += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseDown);
            this.rightSizingBtn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.sizingBtnMouseUp);
        }
        private void SizingLocation()
        {
            topLeftSizingBtn.Location = new Point(0, 0);
            topRightSizingBtn.Location = new Point(this.Width - topRightSizingBtn.Width, 0);

            botLeftSizingBtn.Location = new Point(0, this.Height - botLeftSizingBtn.Height);
            botRightSizingBtn.Location = new Point(this.Width - botRightSizingBtn.Width, this.Height - botRightSizingBtn.Height);

            topSizingBtn.Location = new Point((this.Width - topSizingBtn.Width) / 2, 0);
            bottomSizingBtn.Location = new Point((this.Width - bottomSizingBtn.Width) / 2, this.Height - bottomSizingBtn.Height);

            leftSizingBtn.Location = new Point(0, (this.Height - leftSizingBtn.Height) / 2);
            rightSizingBtn.Location = new Point(this.Width - rightSizingBtn.Width, (this.Height - rightSizingBtn.Height) / 2);
        }
        private void ShowSizing(bool stat)
        {
            topLeftSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.TopLeft)>0);
            topRightSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.TopRight) > 0);

            botLeftSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.BottomLeft) > 0);
            botRightSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.BottomRight) > 0);

            topSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.Top) > 0);
            bottomSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.Bottom) > 0);

            leftSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.Left) > 0);
            rightSizingBtn.Visible = stat && ((mySizingOptions & SizingOptions.Right) > 0);

            topLeftSizingBtn.BringToFront();    topRightSizingBtn.BringToFront();
            botLeftSizingBtn.BringToFront();    botRightSizingBtn.BringToFront();
            topSizingBtn.BringToFront();        bottomSizingBtn.BringToFront();
            leftSizingBtn.BringToFront();       rightSizingBtn.BringToFront();
        }

        private void sizingBtnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            allowResize = true;
        }
        private void sizingBtnMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            allowResize = false;
        }
        private void sizingBtnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (!allowResize) return;
            TimeSpan ts = DateTime.Now.Subtract(lastSizingTime);
            if (ts.Milliseconds < constMouseMoveInterval) return;

            lastSizingTime = DateTime.Now;

            //test.Text = "(" + e.X.ToString() + "," + e.Y.ToString() + ")";
            PictureBox sizingBtn = (PictureBox)sender;

            //Top-Left sizing
            if ((sizingBtn.Name == topLeftSizingBtn.Name) && ((this.mySizingOptions & SizingOptions.TopLeft) > 0))
            {
                sizedRec.Size = new Size(this.Width - e.X, this.Height - e.Y);
                sizedRec.Location = new Point(this.Location.X + e.X, this.Location.Y + e.Y);
            }
            //Top-right sizing
            if ((sizingBtn.Name == topRightSizingBtn.Name) && ((this.mySizingOptions & SizingOptions.TopRight) > 0))
            {
                sizedRec.Size = new Size(this.Width + e.X, this.Height - e.Y);
                sizedRec.Location = new Point(this.Location.X, this.Location.Y + e.Y);
            }
            //Bottom-Left sizing
            if (sizingBtn.Name == botLeftSizingBtn.Name && ((this.mySizingOptions & SizingOptions.BottomLeft) > 0))
            {
                sizedRec.Size = new Size(this.Width - e.X, this.Height + e.Y);
                sizedRec.Location = new Point(this.Location.X + e.X, this.Location.Y);
            }
            //Bottom-Right sizing
            if (sizingBtn.Name == botRightSizingBtn.Name && ((this.mySizingOptions & SizingOptions.BottomRight) > 0))
            {
                sizedRec.Size = new Size(this.Width + e.X, this.Height + e.Y);
                sizedRec.Location = this.Location;
            }

            //Top sizing
            if ((sizingBtn.Name == topSizingBtn.Name) && ((this.mySizingOptions & SizingOptions.Top) > 0))
            {
                sizedRec.Size = new Size(this.Width, this.Height - e.Y);
                sizedRec.Location = new Point(this.Location.X, this.Location.Y + e.Y);
            }
            //Bottom sizing
            if ((sizingBtn.Name == bottomSizingBtn.Name) && ((this.mySizingOptions & SizingOptions.Bottom) > 0))
            {
                sizedRec.Size = new Size(this.Width, this.Height + e.Y);
                sizedRec.Location = new Point(this.Location.X, this.Location.Y);
            }
            //Left sizing
            if ((sizingBtn.Name == leftSizingBtn.Name) && ((this.mySizingOptions & SizingOptions.Left) > 0))
            {
                sizedRec.Size = new Size(this.Width - e.X, this.Height);
                sizedRec.Location = new Point(this.Location.X + e.X, this.Location.Y);
            }
            //Right sizing
            if ((sizingBtn.Name == rightSizingBtn.Name) && ((this.mySizingOptions & SizingOptions.Right) > 0))
            {
                sizedRec.Size = new Size(this.Width + e.X, this.Height);
                sizedRec.Location = new Point(this.Location.X, this.Location.Y);
            }

            if ((sizedRec.Width <= this.minSizingWidth) || (sizedRec.Height < this.minSizingHeight))
            {
                sizedRec.Size = this.Size;
                sizedRec.Location = this.Location;
                return;
            }
            this.Location = sizedRec.Location;
            this.Size = sizedRec.Size;
        }

        #endregion sizing

        private int _weight = 0;
        public int myWeight
        {
            get { return _weight; }
            set { _weight = value; }
        }

        public bool haveCloseButton
        {
            get { return closeBtn.Visible; }
            set
            {
                closeBtn.Visible = value;
                ArrangeControls(); ;
            }
        }
        protected bool fProcessing = false;
        private bool _isExpanded = true;
        public bool isExpanded
        {
            get { return _isExpanded; }
            set
            {
                _isExpanded = value;
                ArrangeControls();
            }
        }

        protected void ArrangeControls()
        {
            try
            {
                fProcessing = true;
                showHideBtn.Visible = true;
                if (isExpanded)
                {
                    this.Size = new Size(saveRec.Size.Width, saveRec.Size.Height);
                    this.Location = new Point(saveRec.Location.X, saveRec.Location.Y);

                    int lastX = this.Width - 4;
                    int lastY = -2;
                    if (closeBtn.Visible)
                    {
                        closeBtn.Location = new System.Drawing.Point(lastX - closeBtn.Width, lastY);
                        lastX = closeBtn.Location.X; lastY = closeBtn.Location.Y;
                        closeBtn.BringToFront();
                    }
                    if (showHideBtn.Visible)
                    {
                        showHideBtn.Location = new System.Drawing.Point(lastX - showHideBtn.Width, lastY);
                        lastX = showHideBtn.Location.X; lastY = showHideBtn.Location.Y;
                    }
                    switch (this.myIconLocations)
                    {
                        case IconLocations.TopRight:
                            this.showHideBtn.Image = Properties.Resources.goUp;
                            break;
                        case IconLocations.TopLeft:
                            this.showHideBtn.Image = Properties.Resources.goUp;
                            break;

                        case IconLocations.BottomRight:
                            this.showHideBtn.Image = Properties.Resources.goDown;
                            break;
                        case IconLocations.BottomLeft:
                            this.showHideBtn.Image = Properties.Resources.goDown;
                            break;
                        case IconLocations.None:
                        default:
                            showHideBtn.Visible = false;
                            break;
                    }
                }
                else
                {
                    this.Size = new Size(showHideBtn.Width, showHideBtn.Height);
                    switch (this.myIconLocations)
                    {
                        case IconLocations.TopRight:
                             this.showHideBtn.Image = Properties.Resources.goDown;
                             this.Location = new Point(saveRec.Location.X + saveRec.Size.Width - showHideBtn.Width - 3, saveRec.Location.Y);
                             break;
                        case IconLocations.TopLeft:
                             this.showHideBtn.Image = Properties.Resources.goDown;
                             this.Location = new Point(saveRec.Location.X - showHideBtn.Width+7, saveRec.Location.Y);
                             break;

                        case IconLocations.BottomRight:
                             this.showHideBtn.Image = Properties.Resources.goUp;
                             this.Location = new Point(saveRec.Location.X + saveRec.Size.Width - showHideBtn.Width - 3,
                                                       saveRec.Location.Y + saveRec.Size.Height - showHideBtn.Height - 3);
                             break;
                        case IconLocations.BottomLeft:
                             this.showHideBtn.Image = Properties.Resources.goUp;
                             this.Location = new Point(saveRec.Location.X - 3,
                                                       saveRec.Location.Y + saveRec.Size.Height - showHideBtn.Height - 3);
                             break;
                        case IconLocations.None:
                        default:
                             this.Size = new Size(0,0);
                             break;
                    }
                    showHideBtn.Location = new Point(0, 0);
                    closeBtn.Location = new Point(0, 0);
                }
                this.BringToFront();
                showHideBtn.BringToFront();
                fProcessing = false;
            }
            catch (Exception er)
            {
                fProcessing = false;
                SysLibs.ThrowException(er);
            }
        }
        private Rectangle saveRec = new Rectangle();
        public void Test(Rectangle rec){saveRec=rec;}

        private PictureBox closeBtn = new PictureBox();
        private PictureBox showHideBtn = new PictureBox();

        public delegate bool OnClosing(object sender);
        public delegate void OnShowStateChanged(object sender);
        public event OnClosing myOnClosing = null;
        public event OnShowStateChanged myOnShowStateChanged = null;
        protected virtual void OnCloseHandler(object sender, EventArgs e)
        {
            if (myOnClosing != null && !myOnClosing(this)) return;
            this.Visible = false;
        }
        protected virtual void OnExpandStateChangedHandler(object sender, EventArgs e)
        {
            try
            {
                this.isExpanded = !this.isExpanded;
                ArrangeControls();
                if (myOnShowStateChanged != null) myOnShowStateChanged(sender);
            }
            catch (Exception er)
            {
                SysLibs.ThrowException(er);
            }
        }

        protected override void OnResize(EventArgs e)
        {
            try
            {
                if (fProcessing) return;
                fProcessing = true;

                //if (this.Parent != null)
                //{
                //    int x = this.Location.X, y = this.Location.Y;
                //    if (this.Location.X < 0) x = 0;
                //    if (this.Location.Y < 0) y = 0;
                //    this.Location = new Point(x, y);
                    
                //    if (this.Location.X + this.Width > this.Parent.Width)
                //        this.Width = this.Parent.Width - this.Location.X;
                //    if (this.Location.Y + this.Height > this.Parent.Height)
                //        this.Height = this.Parent.Height - this.Location.Y;
                //}
                base.OnResize(e);
                if (this.isExpanded) saveRec = new Rectangle(this.Location, this.Size);
                SizingLocation();
                ArrangeControls();

                fProcessing = false;
            }
            catch (Exception er)
            {
                fProcessing = false;
                SysLibs.ThrowException(er);
            }
        }
        protected override void OnVisibleChanged(EventArgs eventargs)
        {
            base.OnVisibleChanged(eventargs);
            ArrangeControls();
        }
        //protected override void OnSizeChanged(EventArgs eventargs)
        //{
        //    base.OnSizeChanged(eventargs);
        //}
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if ((msg.Msg == Consts.WM_KEYDOWN) || (msg.Msg == Consts.WM_SYSKEYDOWN))
            {
                if ((keyData & Keys.ControlKey)==Keys.ControlKey)
                {
                    fShowSizing =!fShowSizing;
                }
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }
    }

}
